using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Maui.Controls;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace MauiBuilder.ViewModels
{
    /// <summary>
    /// Web消息模型
    /// </summary>
    public partial class WebMessage : ObservableObject
    {
        /// <summary>
        /// 消息唯一标识符
        /// </summary>
        [ObservableProperty]
        private string _id = Guid.NewGuid().ToString();

        /// <summary>
        /// 消息时间戳
        /// </summary>
        [ObservableProperty]
        private DateTime _time = DateTime.Now;

        /// <summary>
        /// 消息来源（"C#" 或 "JS"）
        /// </summary>
        [ObservableProperty]
        private string _source = string.Empty;

        /// <summary>
        /// 消息内容
        /// </summary>
        [ObservableProperty]
        private string _message = string.Empty;

        /// <summary>
        /// 消息附加数据
        /// </summary>
        [ObservableProperty]
        private string _data = string.Empty;

        /// <summary>
        /// 格式化的时间文本
        /// </summary>
        public string TimeText => Time.ToString("HH:mm:ss.fff");

        /// <summary>
        /// 消息来源图标
        /// </summary>
        public string SourceIcon => Source switch
        {
            "C#" => "🔷",
            "JS" => "🟨",
            _ => "📝"
        };

        /// <summary>
        /// 消息来源颜色
        /// </summary>
        public Color SourceColor => Source switch
        {
            "C#" => Colors.Blue,
            "JS" => Colors.Orange,
            _ => Colors.Gray
        };
    }

    /// <summary>
    /// HybridWebView页面的视图模型
    /// 实现JavaScript和C#/.NET之间的双向通信
    /// </summary>
    public partial class HybridWebViewModel : BaseViewModel
    {
        /// <summary>
        /// HybridWebView控件引用
        /// </summary>
        private HybridWebView? _hybridWebView;

        /// <summary>
        /// tab选卡选中类型
        /// </summary>
        [ObservableProperty]
        private bool _tabType = true;

        /// <summary>
        /// 消息集合
        /// </summary>
        [ObservableProperty]
        private ObservableCollection<WebMessage> _messages = new();

        /// <summary>
        /// 要发送到JavaScript的消息内容
        /// </summary>
        [ObservableProperty]
        private string _messageToSend = string.Empty;

        /// <summary>
        /// 要执行的JavaScript代码
        /// </summary>
        [ObservableProperty]
        private string _jsCodeToExecute = "function exJS(){alert('Hello from C#!');} exJS();";

        /// <summary>
        /// HybridWebViewModel构造函数
        /// </summary>
        public HybridWebViewModel()
        {
            AddMessage("C#", "系统初始化", "HybridWebView ViewModel 已创建");
        }

        /// <summary>
        /// 设置HybridWebView引用
        /// </summary>
        /// <param name="hybridWebView">HybridWebView控件实例</param>
        public void SetHybridWebView(HybridWebView hybridWebView)
        {
            _hybridWebView = hybridWebView;
            _hybridWebView.SetInvokeJavaScriptTarget(this);
            AddMessage("C#", "HybridWebView已设置", "准备就绪");
        }

        [RelayCommand]
        private void OptionSelected(string option)
        {
            TabType = option == "HybridWebViewTab";
        }
        /// <summary>
        /// 发送消息到JavaScript命令
        /// </summary>
        [RelayCommand]
        private void OnSendMessageToJs()
        {
            if (string.IsNullOrWhiteSpace(MessageToSend) || _hybridWebView == null)
                return;

            try
            {
                // 使用HybridWebView的SendRawMessage方法发送消息
                _hybridWebView.SendRawMessage(MessageToSend);
                AddMessage("C#", "发送消息到JS", MessageToSend);
                
                MessageToSend = string.Empty;
            }
            catch (Exception ex)
            {
                AddMessage("C#", "发送消息失败", ex.Message);
            }
        }

        /// <summary>
        /// 执行JavaScript代码命令
        /// </summary>
        [RelayCommand]
        private async Task OnExecuteJavaScript()
        {
            if (string.IsNullOrWhiteSpace(JsCodeToExecute) || _hybridWebView == null)
                return;

            try
            {
                var result = await _hybridWebView.EvaluateJavaScriptAsync(JsCodeToExecute);
                AddMessage("C#", "执行JS代码", $"代码: {JsCodeToExecute}\n结果: {result}");
            }
            catch (Exception ex)
            {
                AddMessage("C#", "JS执行失败", ex.Message);
            }
        }

        /// <summary>
        /// 获取网页信息命令
        /// </summary>
        [RelayCommand]
        private async Task OnGetWebPageInfo()
        {
            if (_hybridWebView == null)
                return;

            try
            {
                var title = await _hybridWebView.EvaluateJavaScriptAsync("document.title");
                var url = await _hybridWebView.EvaluateJavaScriptAsync("window.location.href");
                
                AddMessage("C#", "获取页面信息", $"标题: {title}\nURL: {url}");
            }
            catch (Exception ex)
            {
                AddMessage("C#", "获取信息失败", ex.Message);
            }
        }

        /// <summary>
        /// 带参数的异步JavaScript调用命令
        /// </summary>
        [RelayCommand]
        public async Task OnEvaluateMeWithParamsAndAsyncReturn()
        {
            try
            {
                Dictionary<string, string>? asyncResult = await _hybridWebView.InvokeJavaScriptAsync<Dictionary<string, string>>(
                "EvaluateMeWithParamsAndAsyncReturn", // JavaScript方法名
                HybridSampleJSContext.Default.DictionaryStringString, // 返回类型的JSON序列化信息
                ["new_key", "new_value"], // 参数值
                [HybridSampleJSContext.Default.String, HybridSampleJSContext.Default.String]); // 每个参数的JSON序列化信息
                
                AddMessage("C#", "异步调用完成", $"结果: {JsonSerializer.Serialize(asyncResult) ?? "无返回值"}");
            }
            catch (Exception ex)
            {
                AddMessage("C#", "异步调用失败", ex.Message);
            }
        }

        /// <summary>
        /// 清空消息列表命令
        /// </summary>
        [RelayCommand]
        private void OnClearMessages()
        {
            Messages.Clear();
            AddMessage("C#", "清空消息", "消息列表已清空");
        }

        /// <summary>
        /// HybridWebView的JSON序列化上下文
        /// </summary>
        [JsonSourceGenerationOptions(WriteIndented = true)]
        [JsonSerializable(typeof(Dictionary<string, string>))]
        [JsonSerializable(typeof(string))]
        internal partial class HybridSampleJSContext : JsonSerializerContext
        {
            // 此类型的属性指定了JSON序列化信息，以在修剪构建中保留类型结构
        }

        /// <summary>
        /// 处理来自JavaScript的消息
        /// </summary>
        /// <param name="message">来自JavaScript的消息内容</param>
        public void HandleJavaScriptMessage(string message)
        {
            // 如果不是JSON格式，就当作简单消息处理
            AddMessage("JS", "原始消息", message);
        }

        #region 同步和异步方法示例

        /// <summary>
        /// 同步工作方法示例
        /// </summary>
        public void DoSyncWork()
        {
            Debug.WriteLine("DoSyncWork");
            AddMessage("C#", "同步方法调用", "DoSyncWork");
        }

        /// <summary>
        /// 带参数的同步工作方法示例
        /// </summary>
        /// <param name="i">整数参数</param>
        /// <param name="s">字符串参数</param>
        public void DoSyncWorkParams(int i, string s)
        {
            AddMessage("C#", "带参数同步方法调用", $"DoSyncWorkParams: {i}, {s}");
        }

        /// <summary>
        /// 带返回值的同步工作方法示例
        /// </summary>
        /// <returns>返回字符串结果</returns>
        public string DoSyncWorkReturn()
        {
            AddMessage("C#", "带返回值同步方法调用", "DoSyncWorkReturn");
            return "Hello from C#!";
        }

        /// <summary>
        /// 带参数和返回值的同步工作方法示例
        /// </summary>
        /// <param name="i">整数参数</param>
        /// <param name="s">字符串参数</param>
        /// <returns>返回SyncReturn对象</returns>
        public SyncReturn DoSyncWorkParamsReturn(int i, string s)
        {
            AddMessage("C#", "带参数和返回值同步方法调用", $"DoSyncWorkParamReturn: {i}, {s}");
            return new SyncReturn
            {
                Message = "Hello from C#!" + s,
                Value = i
            };
        }

        /// <summary>
        /// 异步工作方法示例
        /// </summary>
        public async Task DoAsyncWork()
        {
            Debug.WriteLine("DoAsyncWork");
            AddMessage("C#", "异步方法调用", "DoAsyncWork 开始");
            await Task.Delay(1000);
            AddMessage("C#", "异步方法完成", "DoAsyncWork 完成");
        }

        /// <summary>
        /// 带参数的异步工作方法示例
        /// </summary>
        /// <param name="i">整数参数</param>
        /// <param name="s">字符串参数</param>
        public async Task DoAsyncWorkParams(int i, string s)
        {
            Debug.WriteLine($"DoAsyncWorkParams: {i}, {s}");
            AddMessage("C#", "带参数异步方法调用", $"DoAsyncWorkParams: {i}, {s} 开始");
            await Task.Delay(1000);
            AddMessage("C#", "带参数异步方法完成", $"DoAsyncWorkParams: {i}, {s} 完成");
        }

        /// <summary>
        /// 带返回值的异步工作方法示例
        /// </summary>
        /// <returns>返回字符串结果</returns>
        public async Task<String> DoAsyncWorkReturn()
        {
            Debug.WriteLine("DoAsyncWorkReturn");
            AddMessage("C#", "带返回值异步方法调用", "DoAsyncWorkReturn 开始");
            await Task.Delay(1000);
            AddMessage("C#", "带返回值异步方法完成", "DoAsyncWorkReturn 完成");
            return "Hello from C#!";
        }

        /// <summary>
        /// 带参数和返回值的异步工作方法示例
        /// </summary>
        /// <param name="i">整数参数</param>
        /// <param name="s">字符串参数</param>
        /// <returns>返回SyncReturn对象</returns>
        public async Task<SyncReturn> DoAsyncWorkParamsReturn(int i, string s)
        {
            Debug.WriteLine($"DoAsyncWorkParamsReturn: {i}, {s}");
            AddMessage("C#", "带参数和返回值异步方法调用", $"DoAsyncWorkParamsReturn: {i}, {s} 开始");
            await Task.Delay(1000);
            AddMessage("C#", "带参数和返回值异步方法完成", $"DoAsyncWorkParamsReturn: {i}, {s} 完成");
            return new SyncReturn
            {
                Message = "Hello from C#!" + s,
                Value = i
            };
        }

        #endregion

        /// <summary>
        /// 添加消息到列表
        /// </summary>
        /// <param name="source">消息来源</param>
        /// <param name="message">消息内容</param>
        /// <param name="data">附加数据</param>
        private void AddMessage(string source, string message, string data = "")
        {
            var webMessage = new WebMessage
            {
                Source = source,
                Message = message,
                Data = data,
                Time = DateTime.Now
            };

            MainThread.BeginInvokeOnMainThread(() =>
            {
                Messages.Insert(0, webMessage);

                // 限制消息数量
                while (Messages.Count > 100)
                {
                    Messages.RemoveAt(Messages.Count - 1);
                }
            });
        }

        /// <summary>
        /// 页面消失时的清理
        /// </summary>
        public void OnDisappearing()
        {
            // HybridWebView不需要特殊清理
        }
    }

    /// <summary>
    /// 同步方法返回值类型
    /// </summary>
    public class SyncReturn
    {
        /// <summary>
        /// 消息内容
        /// </summary>
        public string? Message { get; set; }
        
        /// <summary>
        /// 数值
        /// </summary>
        public int Value { get; set; }
    }
}